import { Fragment, defineComponent, toRaw, watch } from "vue";
import * as THREE from "three";
import { draw, miniMap, point, tip, layer } from './LibraryShow.module.scss';
import { initLibrary } from "@/utils/library/init";
import { initLibrary2 } from "@/utils/cannon/init";
import { Library, libraryState } from "@/utils/library";
import { PointerLockControls } from "three/examples/jsm/controls/PointerLockControls.js";
import { isMobile } from "@/App";

export default defineComponent({
    name: 'LibraryShow',
    data() {
        return {
            scene: null as any,
            canvas: null as any,
            camera: null as any,
            controls: null as any,
            renderer: null as any,
            clock: new THREE.Clock(),
            model: null as any,
            requestAnimationFrameId: null as any,
        }
    },
    mounted() {
        libraryState.isMobile = isMobile;
        // 物理引擎
        initLibrary2();
        // 八叉树-切换模型
        // initLibrary();

        // 切换场景
        // this.init();
        // this.watchSceneIndex();
    },
    methods: {
        init() {
            // 获取canvas
            this.canvas = document.getElementById("library") as HTMLElement;
            // 场景
            this.scene = this.createScene1();
            // 渲染器
            this.addRenderer();
            this.resizeWindow();
        },
        createScene1() {
            const scene = new THREE.Scene();
            this.addCamera(scene);
            this.addControls();
            this.addLight1(scene);
            this.addLight2(scene);
            this.model = new Library(scene, this.camera, this.controls, 1);
            return scene;
        },
        createScene2() {
            const scene = new THREE.Scene();
            this.addCamera(scene);
            this.addControls();
            this.addLight1(scene);
            this.addLight2(scene);
            this.model = new Library(scene, this.camera, this.controls, 2);
            return scene;
        },
        addCamera(scene) {
            this.camera = new THREE.PerspectiveCamera(
                75, //视角
                window.innerWidth / window.innerHeight, //aspect视锥长宽比
                0.1, //near
                10000 //far
            );
            this.camera.rotation.order = "YXZ"; //默认旋转顺序是 'XYZ',设置相机旋转的顺序的属性。这个属性指定了欧拉角（Euler angles）的旋转顺序
            this.camera.lookAt(0, 0, 0);
            this.camera.position.set(0, 1, 5);
            scene.add(this.camera);
        },
        addControls() {
            // 添加相机控件-指针
            this.controls = new PointerLockControls(this.camera, this.canvas);
        },
        addRenderer() {
            this.renderer = new THREE.WebGLRenderer({ canvas: this.canvas });
            this.renderer.setSize(window.innerWidth, window.innerHeight);
            // 像素比（和浏览器一致）
            this.renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
            // 背景色
            this.renderer.setClearColor(new THREE.Color(0xffffff), 1);
            // 动画
            this.animation();
        },
        addLight1(scene) {
            const fillLight1 = new THREE.HemisphereLight(0xffffff, 0xffffff, 1.5);
            fillLight1.position.set(2, 1, 1);
            scene.add(fillLight1);
        },
        addLight2(scene) {
            const directionalLight = new THREE.DirectionalLight(0xffffff, 2.5);
            directionalLight.position.set(-5, 25, -1);
            directionalLight.castShadow = true;
            directionalLight.shadow.camera.near = 0.01;
            directionalLight.shadow.camera.far = 500;
            directionalLight.shadow.camera.right = 30;
            directionalLight.shadow.camera.left = -30;
            directionalLight.shadow.camera.top = 30;
            directionalLight.shadow.camera.bottom = -30;
            directionalLight.shadow.mapSize.width = 1024;
            directionalLight.shadow.mapSize.height = 1024;
            directionalLight.shadow.radius = 4;
            directionalLight.shadow.bias = -0.00006;
            scene.add(directionalLight);
        },
        animation() {
            if (libraryState.tweenPosition) libraryState.tweenPosition.update();
            //指定每一帧更新时间
            if (!libraryState.spriteTarget && this.model)
                this.model.start(this.clock.getDelta());
            // 渲染场景
            if (this.scene && this.camera) this.renderer.render(toRaw(this.scene), toRaw(this.camera));
            this.requestAnimationFrameId = requestAnimationFrame(this.animation);
        },
        resizeWindow() {
            window.addEventListener("resize", () => {
                // 更新宽高比
                this.camera.aspect = window.innerWidth / window.innerHeight;
                // 更新相机的投影矩阵
                this.camera.updateProjectionMatrix();

                this.renderer.setSize(window.innerWidth, window.innerHeight);
                // 设置像素比
                this.renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
            });
        },
        clearSceneStatus() {
            // 取消上一个场景的动画帧请求，以停止渲染当前场景的动画
            cancelAnimationFrame(this.requestAnimationFrameId);
            try {
                this.scene.remove(this.model.modelObj);
            } catch (error) {
                console.log('scene.remove', error);
            }
            //释放场景
            this.scene.traverse((child: any) => {
                if (child.material) {
                    try {
                        // 释放材质
                        child.material?.uniforms?.texture?.value?.dispose();
                        child.material?.dispose();
                    } catch (error) {
                        console.log('释放材质', error);
                    }
                }
                if (child.geometry) {
                    try {
                        // 释放几何体
                        child.geometry?.dispose();
                    } catch (error) {
                        console.log('释放几何体', error);

                    }
                }
                child = null;
            });
            try {
                this.renderer.dispose();
            } catch (error) {
                console.log('this.renderer.dispose', error);
            }
            //销毁渲染器中的缓冲区
            // this.renderer.forceContextLoss(); //强制释放 WebGL 上下文，确保所有 WebGL 资源被正确释放,需要在特殊情况下使用，避免报THREE.WebGLRenderer: Context Lost.
            try {
                this.renderer.dispose();
            } catch (error) {
                console.log('this.renderer.dispose', error);
            }
            this.renderer.domElement = null;
            this.renderer = null;
            libraryState.joyStick?.removeDom();
            libraryState.joyStick = null;
            // 回正胶囊位置
            libraryState.player?.check(true);
        },
        watchSceneIndex() {
            watch(
                () => libraryState.sceneIndex,
                (newValue) => {
                    console.log("监听切换场景", newValue);
                    this.clearSceneStatus();
                    switch (newValue) {
                        case 1:
                            this.scene = this.createScene1();
                            break;
                        case 2:
                            this.scene = this.createScene2();
                            break;
                        default:
                            this.scene = this.createScene1();
                            break;
                    }
                }
            );
        }
    },
    render() {
        return <Fragment>
            <canvas id="library" class={draw}>浏览器不支持canvas</canvas>
            {libraryState.isEnter && <div class={tip}>
                是否进入?
                <div onClick={(e) => {
                    if (!libraryState.isMobile) {
                        e.stopPropagation();
                        libraryState.sceneIndex = 2;
                    }
                }}
                    onTouchstart={(e) => {
                        if (libraryState.isMobile) {
                            e.stopPropagation();
                            libraryState.sceneIndex = 2;
                        }
                    }}
                >确认</div>
            </div>}
            {/* <div id="joystickContainer"></div> */}
        </Fragment>;
    },
});